package com.fileFormatConvert;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 图片格式转换器，支持不同类型的输入（路径、文件、字节数组、输入流），以及不同类型的输出（字节数组、输出流）。
 */
public class ImageConverter {

    /**
     * 从输入流读取并转换为目标格式，返回字节数组。
     *
     * @param inputStream  输入流
     * @param targetFormat 目标格式（例如 JPEG、PNG）
     * @return 返回字节数组
     * @throws ImageProcessingException 异常处理
     */
    public static byte[] convertToTargetFormatAndGetByteArray(InputStream inputStream, ImageFormat targetFormat)
            throws ImageProcessingException, IOException {
        BufferedImage image = readImageFromStream(inputStream);
        return convertImageToByteArray(image, targetFormat);
    }

    /**
     * 从字节数组读取并转换为目标格式，返回字节数组。
     *
     * @param imageData    图片字节数组
     * @param targetFormat 目标格式（例如 JPEG、PNG）
     * @return 返回字节数组
     * @throws ImageProcessingException 异常处理
     */
    public static byte[] convertToTargetFormatAndGetByteArray(byte[] imageData, ImageFormat targetFormat)
            throws ImageProcessingException, IOException {
        InputStream inputStream = new ByteArrayInputStream(imageData);
        return convertToTargetFormatAndGetByteArray(inputStream, targetFormat);
    }

    /**
     * 从文件读取并转换为目标格式，返回字节数组。
     *
     * @param imageFile    图片文件
     * @param targetFormat 目标格式（例如 JPEG、PNG）
     * @return 返回字节数组
     * @throws ImageProcessingException 异常处理
     */
    public static byte[] convertToTargetFormatAndGetByteArray(File imageFile, ImageFormat targetFormat)
            throws ImageProcessingException {
        try (InputStream inputStream = new FileInputStream(imageFile)) {
            return convertToTargetFormatAndGetByteArray(inputStream, targetFormat);
        } catch (IOException e) {
            throw new ImageProcessingException("Failed to read image from file: " + imageFile.getName(), e);
        }
    }

    /**
     * 从输入流读取并转换为目标格式，返回输出流。
     *
     * @param inputStream  输入流
     * @param targetFormat 目标格式（例如 JPEG、PNG）
     * @return 返回输出流
     * @throws ImageProcessingException 异常处理
     */
    public static OutputStream convertToTargetFormatAndGetStream(InputStream inputStream, ImageFormat targetFormat)
            throws ImageProcessingException, IOException {
        BufferedImage image = readImageFromStream(inputStream);
        return convertImageToOutputStream(image, targetFormat);
    }

    /**
     * 从字节数组读取并转换为目标格式，返回输出流。
     *
     * @param imageData    图片字节数组
     * @param targetFormat 目标格式（例如 JPEG、PNG）
     * @return 返回输出流
     * @throws ImageProcessingException 异常处理
     */
    public static OutputStream convertToTargetFormatAndGetStream(byte[] imageData, ImageFormat targetFormat)
            throws ImageProcessingException, IOException {
        InputStream inputStream = new ByteArrayInputStream(imageData);
        return convertToTargetFormatAndGetStream(inputStream, targetFormat);
    }

    /**
     * 从文件读取并转换为目标格式，返回输出流。
     *
     * @param imageFile    图片文件
     * @param targetFormat 目标格式（例如 JPEG、PNG）
     * @return 返回输出流
     * @throws ImageProcessingException 异常处理
     */
    public static OutputStream convertToTargetFormatAndGetStream(File imageFile, ImageFormat targetFormat)
            throws ImageProcessingException {
        String name = imageFile.getName();
        if (!ImageFormat.isValidFormat(name)) {
            throw new ImageProcessingException("current file is not an image");
        }

        try (InputStream inputStream = Files.newInputStream(imageFile.toPath())) {
            return convertToTargetFormatAndGetStream(inputStream, targetFormat);
        } catch (IOException e) {
            throw new ImageProcessingException("Failed to read image from file: " + imageFile.getName(), e);
        }
    }

    /**
     * 从输入流读取图像数据并转换为 BufferedImage。
     *
     * @param inputStream 输入流
     * @return BufferedImage
     * @throws ImageProcessingException 异常处理
     */
    private static BufferedImage readImageFromStream(InputStream inputStream) throws ImageProcessingException {
        BufferedImage image;
        try {
            image = ImageIO.read(inputStream);  // 读取图片
            if (image == null) {
                throw new ImageProcessingException("Image could not be read from stream.");
            }
        } catch (IOException e) {
            throw new ImageProcessingException("Failed to read image from input stream", e);
        }
        return image;
    }

    /**
     * 将图像转换为字节数组。
     *
     * @param image        BufferedImage
     * @param targetFormat 目标格式
     * @return 返回字节数组
     * @throws IOException 异常
     */
    private static byte[] convertImageToByteArray(BufferedImage image, ImageFormat targetFormat) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(image, targetFormat.getFormatName(), byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }

    /**
     * 从字节数组创建输出流并写入图像数据。
     *
     * @param image        BufferedImage
     * @param targetFormat 目标格式
     * @return 返回输出流
     * @throws IOException 异常
     */
    private static OutputStream convertImageToOutputStream(BufferedImage image, ImageFormat targetFormat) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, targetFormat.getFormatName(), outputStream);
        return outputStream;
    }

}
